#include "GAF_ControlAction.h"

namespace GAF
{
	ControlMap::ControlMap()
	{
		m_pdValues = NULL;
		m_nCtrlCount = GAF_CTRLMAP_COUNT;
	}

	ControlMap::ControlMap(const ControlMap& amScr)
	{
		m_pdValues = NULL;
		m_nCtrlCount = GAF_CTRLMAP_COUNT;
		CopyOther(amScr);
	}

	ControlMap::~ControlMap()
	{
		if(m_pdValues != NULL)
			GAF_DELETE_ARY(m_pdValues);


		m_mapMarks.clear();
	}


	void ControlMap::Adjust(double dValue)
	{
		// 初始化
		if(m_mapMarks.empty())
		{
			NewValues();
			m_mapMarks.insert(MarkMap::value_type(GAF_CTRLMAP_LEFT, GAF_CTRLMAP_ZERO));
			m_mapMarks.insert(MarkMap::value_type(GAF_CTRLMAP_RIGHT, GAF_CTRLMAP_ZERO));
		}

		// 调整值
		for(int _i = 0; _i < m_nCtrlCount; _i++)
			m_pdValues[_i] += dValue;

		// 调整标记点
		for(MarkMap::iterator _it = m_mapMarks.begin();
			_it != m_mapMarks.end();
			_it++)
		{
			_it->second += dValue;
		}
	}

	void ControlMap::AddMark(UINT nID, double dValue)
	{
		// 初始化
		if(m_mapMarks.empty())
		{
			NewValues();
			m_mapMarks.insert(MarkMap::value_type(GAF_CTRLMAP_LEFT, GAF_CTRLMAP_ZERO));
			m_mapMarks.insert(MarkMap::value_type(GAF_CTRLMAP_RIGHT, GAF_CTRLMAP_ZERO));
		}

		// 检索前后标记
		UINT _nPrevID, _nNextID;
		Switch(nID, _nPrevID, _nNextID);

		// 计算变化值
		Transition(_nPrevID, m_pdValues[_nPrevID], nID, dValue);
		Transition(nID, dValue, _nNextID, m_pdValues[_nNextID]);

		// 记录标记
		m_mapMarks[nID] = dValue;
	}

	void ControlMap::RemoveMark(UINT nID)
	{
		// 检索前后标记
		UINT _nPrevID, _nNextID;
		Switch(nID, _nPrevID, _nNextID);

		// 计算变化值
		Transition(_nPrevID, m_pdValues[_nPrevID], _nNextID, m_pdValues[_nNextID]);

		// 移除标记
		m_mapMarks.erase(nID);
	}

	const double* ControlMap::Values()
	{
		return m_pdValues;
	}

	void ControlMap::operator=(const ControlMap& amOther)
	{
		CopyOther(amOther);
	}

	void ControlMap::CopyOther(const ControlMap& amOther)
	{
		m_nCtrlCount = amOther.m_nCtrlCount;
		NewValues();
		SYS_MEMCPY(m_pdValues, amOther.m_pdValues, sizeof(double) * m_nCtrlCount);
		m_mapMarks = amOther.m_mapMarks;
	}

	void ControlMap::Switch(UINT nID, UINT& nPrevID, UINT& nNextID)
	{
		nPrevID = GAF_CTRLMAP_LEFT;
		nNextID = GAF_CTRLMAP_RIGHT;
		for(MarkMap::iterator _it = m_mapMarks.begin();
			_it != m_mapMarks.end();
			_it++)
		{
			if(_it->first > nPrevID && _it->first < nID)
				nPrevID = _it->first;
			else if(_it->first < nNextID && _it->first > nID)
				nNextID = _it->first;
		}
	}

	void ControlMap::Transition(UINT nLeftID, double nLeftValue, UINT nRightID, double dRightValue)
	{
		UINT _nChange = nRightID - nLeftID;
		double _dChange = dRightValue - nLeftValue;

		if(_nChange == 0)
			m_pdValues[nLeftID] = m_pdValues[nLeftID] + _dChange;
		else
		{
			for(UINT _nID = 0; _nID <= _nChange; _nID++)
			{
				m_pdValues[nLeftID + _nID] = m_pdValues[nLeftID] + _dChange * _nID / _nChange;
			}
		}
	}

	void ControlMap::NewValues()
	{
		if(m_pdValues != NULL)
			GAF_DELETE_ARY(m_pdValues);

		m_pdValues = GAF_NEW_ARY(double, m_nCtrlCount);
		SYS_MEMSET(m_pdValues, 0, sizeof(double) * m_nCtrlCount);
	}



	CtrlItemBase::CtrlItemBase()
	{
		m_isStop = false;
		m_nWay = 1;
		m_nCurCtrl = 0;
		m_nCurTimes = 0;
		m_ttExcess = 0;
	}


	ControlAction::ControlAction()
	{
	}

	ControlAction::~ControlAction()
	{
		for(CtrlItemMap::iterator _it = m_mapControls.begin();
			_it != m_mapControls.end();
			_it++)
		{
			delete _it->second;
		}

		m_mapControls.clear();
	}

	bool ControlAction::OnPlay(Bundle* pbdlParam)
	{
		for(CtrlItemMap::iterator _it = m_mapControls.begin();
			_it != m_mapControls.end();
			_it++)
		{
			_it->second->m_isStop = false;
			_it->second->m_nWay = 1;
			_it->second->m_nCurCtrl = 0;
			_it->second->m_nCurTimes = 0;
			_it->second->m_ttExcess = 0;
		}

		return true;
	}

	bool ControlAction::OnUpdate(TimeTicks ttUsed)
	{
		bool _isContinue = false;

		for(CtrlItemMap::iterator _it = m_mapControls.begin();
			_it != m_mapControls.end();
			_it++)
		{
			if(!_it->second->m_isStop)
			{
				UpdateAttrib(ttUsed, _it->second);
				_isContinue = true;
			}
		}

		return _isContinue;
	}

	bool ControlAction::OnStop()
	{
		return true;
	}

	void ControlAction::UpdateAttrib(TimeTicks ttUsed, CtrlItemBase* pItem)
	{
		// 增加的控制点
		int _ttUsed = ttUsed + pItem->m_ttExcess;
		int _nAddCtrl = _ttUsed / pItem->m_ttOneCtrl;
		pItem->m_ttExcess = _ttUsed % pItem->m_ttOneCtrl;
		pItem->m_nCurCtrl += pItem->m_nWay * _nAddCtrl;

		// 以模式调整属性
		if(pItem->m_amMode == ACTION_AGAIN)
		{
			// 如果超出控制范围
			if(pItem->m_nCurCtrl >= pItem->m_cmControl.m_nCtrlCount - 1)
			{
				pItem->m_nCurCtrl = pItem->m_cmControl.m_nCtrlCount - 1;

				if(++pItem->m_nCurTimes >= pItem->m_nTimes)
				{ // 结束
					ChangeAttrib(pItem, pItem->m_nCurCtrl, pItem->m_nCurCtrl);
					pItem->m_isStop = true;
					return;
				}
				else
				{ // 未结束
					pItem->m_nCurCtrl = 0;
				}
			}

			// 计算调整属性值
			ChangeAttrib(pItem, pItem->m_nCurCtrl, pItem->m_nCurCtrl + 1);
		}
		else if(pItem->m_amMode == ACTION_RETURN)
		{
			if(pItem->m_nWay == 1)
			{ // 正方向
				// 如果超出控制范围
				if(pItem->m_nCurCtrl >= pItem->m_cmControl.m_nCtrlCount - 1)
				{
					pItem->m_nCurCtrl = pItem->m_cmControl.m_nCtrlCount - 1;

					if(++pItem->m_nCurTimes >= pItem->m_nTimes)
					{ // 结束
						ChangeAttrib(pItem, pItem->m_nCurCtrl, pItem->m_nCurCtrl);
						pItem->m_isStop = true;
						return;
					}
					else
					{ // 未结束，调转方向
						pItem->m_nWay = -1;
					}
				}

				// 计算调整属性值
				ChangeAttrib(pItem, pItem->m_nCurCtrl, pItem->m_nCurCtrl + pItem->m_nWay * 1);
			}
			else
			{ // 反方向
				// 如果超出控制范围
				if(pItem->m_nCurCtrl <= 0)
				{
					pItem->m_nCurCtrl = 0;

					if(++pItem->m_nCurTimes >= pItem->m_nTimes)
					{ // 结束
						ChangeAttrib(pItem, pItem->m_nCurCtrl, pItem->m_nCurCtrl);
						pItem->m_isStop = true;
						return;
					}
					else
					{ // 未结束，调转方向
						pItem->m_nWay = 1;
					}
				}

				// 计算调整属性值
				ChangeAttrib(pItem, pItem->m_nCurCtrl, pItem->m_nCurCtrl + pItem->m_nWay * 1);
			}
		}
	}

	void ControlAction::ChangeAttrib(CtrlItemBase* pItem, int nCurCtrl, int nNextCtrl)
	{
		ControlMap& _cm = pItem->m_cmControl;
		double dOneChange = 0.0;

		if(nCurCtrl != nNextCtrl)
		{
			// 计算每毫秒更新属性值
			dOneChange =
				(_cm.Values()[nNextCtrl] - _cm.Values()[nCurCtrl])
				/ pItem->m_ttOneCtrl;
		}

		// 计算更新属性值
		double dChange = _cm.Values()[nCurCtrl] + dOneChange;

		// 调整属性值
		pItem->SetAttrib(dChange);
	}
}
